﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Workflow.ComponentModel;

namespace Argos
{
	public static class Predicates
	{

		#region public static Predicate<PropertyInfo> BindableActivityPropertyMatcher { get; }

		public static Predicate<PropertyInfo> BindableActivityPropertyMatcher
		{
			get
			{
				return delegate(PropertyInfo info)
				{
					Type t = info.DeclaringType;
					MemberInfo[] staticMembers = t.GetMembers(BindingFlags.Public | BindingFlags.Static);
					foreach (MemberInfo statProp in staticMembers)
					{
						Type propType = null;
						if (statProp is FieldInfo)
						{
							propType = ((FieldInfo)statProp).FieldType;
						}
						if (statProp is PropertyInfo)
						{
							propType = ((PropertyInfo)statProp).PropertyType;
						}

						if (propType == typeof(DependencyProperty))
						{
							DependencyProperty dep = (DependencyProperty)t.InvokeMember(statProp.Name, BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField | BindingFlags.GetProperty, null, null, null);
							if (null != dep && dep.Name == info.Name)
							{
								return true;
							}
						}
					}

					return false;
				};
			}
		}

		#endregion

		#region public static Predicate<PropertyInfo> BindableBrowsableActivityPropertyMatcher { get; }

		public static Predicate<PropertyInfo> BindableBrowsableActivityPropertyMatcher
		{
			get
			{
				return delegate(PropertyInfo info)
				{
					return info.IsBrowsable() && BindableActivityPropertyMatcher.Invoke(info);
				};
			}
		}

		#endregion

		#region public static Predicate<PropertyInfo> DefaultPropertyMatcher { get; }

		public static Predicate<PropertyInfo> DefaultPropertyMatcher
		{
			get
			{
				return delegate(PropertyInfo info)
				{
					return info.CanRead && info.CanWrite && info.IsBrowsable();
				};
			}
		}

		#endregion

		#region public static Predicate<Type> DefaultTypeMatcher { get; }

		/// <summary>
		/// Returns the default type matcher that matches no type.
		/// </summary>
		public static Predicate<Type> DefaultTypeMatcher
		{
			get { return delegate(Type t) { return false; }; }
		}

		#endregion

		#region public static Predicate<Type> MessageDeliveryActivityMatcher { get; }

		/// <summary>
		/// Returns a predicate that matches any type that is a message delivery activity.
		/// </summary>
		public static Predicate<Type> MessageDeliveryActivityMatcher
		{
			get
			{
				return delegate(Type t)
				{
					return t.IsMessageDeliveryActivity();
				};
			}
		}

		#endregion

		#region public static Predicate<Type> TargetMonitoringWorkflowTypeMatcher { get; }

		/// <summary>
		/// Returns a predicate that matches any type that is a target monitoring workflow.
		/// </summary>
		/// <remarks>
		/// A target monitoring workflow is any type that inherits either from
		/// <see cref="SequentialWorkflowActivity"/> or <see cref="StateMachineWorkflowActivity"/>
		/// and implements the <see cref="ITargetMonitoringWorkflow"/> interface.
		/// </remarks>
		public static Predicate<Type> TargetMonitoringWorkflowTypeMatcher
		{
			get
			{
				return delegate(Type t)
				{
					return t.IsTargetMonitoringWorkflow();
				};
			}
		}

		#endregion

		#region public static Predicate<Type> TestActivityMatcher { get; }

		/// <summary>
		/// Returns a predicate that matches any type that is a test activity.
		/// </summary>
		/// <remarks>
		/// A test activity is any type that inherits from <see cref="Activity"/> and
		/// is implements the <see cref="ITestActivity"/> interface. In
		/// addition, a test activity must have a public default constructor.
		/// </remarks>
		public static Predicate<Type> TestActivityMatcher
		{
			get
			{
				return delegate(Type t)
				{
					return t.IsTestActivity();
				};
			}
		}

		#endregion

	}
}
